package com.zmn.oms.admin.controller.order;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.common.data.dubbo.interfaces.tags.TagsListRemoteService;
import com.zmn.base.price.common.dto.fixed.FixedErpProductForOmsDRO;
import com.zmn.base.price.common.dto.fixed.FixedErpProductForOmsQuery;
import com.zmn.base.price.common.dto.fixed.FixedItemSimpleDRO;
import com.zmn.base.price.dubbo.interfaces.calculate.FixedFlowRemoteService;
import com.zmn.base.price.dubbo.interfaces.calculate.ItemPriceRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.consts.GlobalConsts;
import com.zmn.oms.admin.controller.OmsBaseController;
import com.zmn.oms.business.interfaces.base.BaseCodeService;
import com.zmn.oms.business.interfaces.price.PriceTableBService;
import com.zmn.oms.business.interfaces.servtype.ServItemBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.vo.KVDict;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.dto.work.modify.CheckQuotationTypeOrderDTO;
import com.zmn.oms.model.entity.advancequote.AdvanceQuoteBaseQuery;
import com.zmn.oms.model.entity.advancequote.AdvanceQuoteItemQuery;
import com.zmn.oms.model.entity.advancequote.AdvanceQuoteOpenQuery;
import com.zmn.oms.model.entity.advancequote.AdvanceQuotePhenQuery;
import com.zmn.oms.model.vo.order.advanceQuote.CategVO;
import com.zmn.oms.model.vo.order.advanceQuote.ProductVO;
import com.zmn.oms.model.vo.order.advanceQuote.QuoteInfoVO;
import com.zmn.oms.model.vo.phenprice.PhenFaultPriceListVO;
import com.zmn.oms.model.vo.phenprice.PhenPriceListVO;
import com.zmn.oms.model.vo.phenprice.PhenPriceVO;
import com.zmn.oms.model.vo.phenprice.PhenServiceItemPriceVO;
import com.zmn.oms.model.vo.price_list.PriceListVO;
import com.zmn.oms.zmn.normal.business.interfaces.order.advancequote.AdvanceQuoteListBService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author sunlife
 * @date:2022/9/20 下午3:07
 * description: 提前付相关接口
 */
@Controller
@RequestMapping("/order/advance")
public class AdvanceController extends OmsBaseController {

    @DubboReference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private TagsListRemoteService tagsListRemoteService;
    @DubboReference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private FixedFlowRemoteService fixedFlowRemoteService;
    @DubboReference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private ItemPriceRemoteService itemPriceRemoteService;

    @Resource
    private ServItemBService servItemBService;
    @Resource
    private AdvanceQuoteListBService advanceQuoteListBService;
    @Resource
    private PriceTableBService priceTableBService;
    @Resource
    private BaseCodeService baseCodeService;


    /**
     * 试点检查
     *
     * @param advanceQuoteOpenQuery
     * @return
     */
    @RequestMapping(value = "checkAdvance")
    @ResponseBody
    public ResultDTO checkAdvance(AdvanceQuoteOpenQuery advanceQuoteOpenQuery) {
        boolean openAdvanceQuote = baseCodeService.isOpenAdvanceQuote(advanceQuoteOpenQuery);
        return ResultDTO.success(openAdvanceQuote ? GlobalConsts.YES : GlobalConsts.NO);
    }

    /**
     *   获取报价信息
     *
     * @param query 查询参数
     * @return 报价信息
     */
    @RequestMapping(value = "getQuoteInfo")
    @ResponseBody
    public ResultDTO getQuoteInfo(@RequestBody AdvanceQuoteBaseQuery query) {

        QuoteInfoVO quoteInfo = new QuoteInfoVO();

        // 检查工单服务类型
        CheckQuotationTypeOrderDTO checkQuotationTypeOrderDTO = CheckQuotationTypeOrderDTO
                .builder()
                .bizType(query.getBizType())
                .channelId(query.getChannelId())
                .cityId(query.getCityId())
                .platWork(query.getPlatWork())
                .productId(query.getShowProductId())
                .sourceType(OrderConsts.ORDER_SOURCE_TYPE_NORMAL)
                .type(OrderConsts.ORDER_TYPE_NEW)
                .build();
        Integer servItemType = servItemBService.getServItemType(checkQuotationTypeOrderDTO);
        // 如果是计价器3.0或者提前付，则需要查询故障现象
        if (servItemType.equals(OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE) ||servItemType.equals(OrderConsts.SERVICE_ITEM_TYPE_FINAL_PRICE)) {
            // 查询故障现象
            ResultDTO<List<KVDict>> resultDTO = this.listFaultPhen(query);
            if (!resultDTO.isStatusBool()) {
                logger.info("获取故障现象失败：{}", resultDTO.getMessage());
            }
            if (CollectionUtil.isNotNullOrEmpty(resultDTO.getData())) {
                quoteInfo.setFaultPhenList(resultDTO.getData());
            }
        }

        //TODO 如果指定了服务项报价，查询服务项信息
        if (CollectionUtil.isNullOrEmpty(quoteInfo.getFaultPhenList())) {
            quoteInfo.setItemList(this.listServiceItem(query).getData());
        }

        return ResultDTO.success(quoteInfo);
    }

    /**
     * 通过前台产品&其他信息获取故障现象
     * @param query 查询参数
     * @return ResultDTO
     */
    @RequestMapping(value = "listFaultPhen")
    @ResponseBody
    public ResultDTO<List<KVDict>> listFaultPhen(@RequestBody AdvanceQuoteBaseQuery query) {

        AdvanceQuoteBaseQuery baseQuery = BeanMapper.map(query, AdvanceQuoteBaseQuery.class);
        List<KVDict> phenList = advanceQuoteListBService.listFaultPhen(baseQuery);

        return ResultDTO.success(phenList);
    }

    /**
     * 通过前台产品&故障现象获取后台二级分类
     * @param query 请求参数
     * @return ResultDTO
     */
    @RequestMapping(value = "listProductCateg")
    @ResponseBody
    public ResultDTO listProductCateg(@RequestBody AdvanceQuotePhenQuery query) {
        AdvanceQuotePhenQuery baseQuery = BeanMapper.map(query, AdvanceQuotePhenQuery.class);
        List<CategVO> categList = advanceQuoteListBService.listProductCateg(baseQuery);

        return ResultDTO.success(categList);
    }

    /**
     * 通过前台产品&其他信息获取后台产品
     * @param query 查询参数
     * @return ResultDTO
     */
    @RequestMapping(value = "listProduct")
    @ResponseBody
    public ResultDTO listProduct(@RequestBody AdvanceQuotePhenQuery query) {

        AdvanceQuotePhenQuery baseQuery = BeanMapper.map(query, AdvanceQuotePhenQuery.class);
        List<ProductVO> productList = advanceQuoteListBService.listProduct(baseQuery);

        return ResultDTO.success(productList);
    }

    // 服务项相关接口******************

    /**
     * 通过前台产品&其他信息获取故障现象
     * @param query 查询参数
     * @return ResultDTO
     */
    @RequestMapping(value = "listServiceItem")
    @ResponseBody
    public ResultDTO<List<KVDict>> listServiceItem(@RequestBody AdvanceQuoteBaseQuery query) {

        AdvanceQuoteBaseQuery baseQuery = BeanMapper.map(query, AdvanceQuoteBaseQuery.class);
        List<KVDict> itemList = advanceQuoteListBService.listServiceItem(baseQuery);

        return ResultDTO.success(itemList);
    }


    /**
     * 通过前台产品&故障现象获取后台二级分类
     * @param query 查询参数
     * @return ResultDTO
     */
    @RequestMapping(value = "listProductCategWithItemId")
    @ResponseBody
    public ResultDTO listProductCategWithItemId(@RequestBody AdvanceQuoteItemQuery query) {
        AdvanceQuoteItemQuery baseQuery = BeanMapper.map(query, AdvanceQuoteItemQuery.class);
        List<CategVO> categList = advanceQuoteListBService.listProductCategWithItemId(baseQuery);

        return ResultDTO.success(categList);
    }


    /**
     * 通过前台产品&其他信息获取后台产品
     * @param query 查询参数
     * @return ResultDTO
     */
    @RequestMapping(value = "listProductWithItem")
    @ResponseBody
    public ResultDTO listProductWithItem(@RequestBody AdvanceQuoteItemQuery query) {
        AdvanceQuoteItemQuery baseQuery = BeanMapper.map(query, AdvanceQuoteItemQuery.class);
        List<ProductVO> productList = advanceQuoteListBService.listProductWithItem(baseQuery);

        return ResultDTO.success(productList);
    }

    /**
     * 价格表
     * @param productId
     * @param cityId
     * @param channelId
     * @param bizType
     * @param type
     * @param plat
     * @param brandId
     * @param tariffType
     * @param orderId
     * @param workId
     * @param itemId
     * @return
     * @throws OmsBaseException
     */
    @RequestMapping(value = "/getProductPriceTable")
    public ModelAndView getProductPriceTable(Integer productId,
                                             Integer cityId,
                                             Integer channelId,
                                             Integer bizType,
                                             Integer type,
                                             Integer plat,
                                             @RequestParam(required = false) Integer brandId,
                                             @RequestParam(required = false) Integer tariffType,
                                             @RequestParam(required = false) Long orderId,
                                             @RequestParam(required = false) Long workId,
                                             @RequestParam(required = false) Integer itemId,
                                             @RequestParam(required = false) Integer categId) throws OmsBaseException {
        ModelAndView mv = new ModelAndView("advancequote/advanceProductPriceTable");
        PriceListVO priceListVO = priceTableBService.getProductPriceTable(productId, cityId, channelId, bizType, brandId, tariffType, orderId, workId, type, plat, Lists.newArrayList(itemId), categId);
        mv.addObject("priceListVO", priceListVO);
        return mv;
    }

    /**
     * 故障现象价格表
     * @param productId
     * @param cityId
     * @param channelId
     * @param bizType
     * @param type
     * @param plat
     * @param brandId
     * @param tariffType
     * @param itemId
     * @return
     * @throws OmsBaseException
     */
    @RequestMapping(value = "/getPhenProductPriceTable")
    public ModelAndView getPhenProductPriceTable(Integer productId,
                                             Integer cityId,
                                             Integer channelId,
                                             Integer bizType,
                                             Integer type,
                                             Integer plat,
                                             @RequestParam(required = false) Integer brandId,
                                             @RequestParam(required = false) Integer tariffType,
                                             @RequestParam(required = false) Integer categId,
                                             @RequestParam(required = false) Integer phenId,
                                             @RequestParam(required = false) String phenName,
                                             @RequestParam(required = false) Integer backProductId) throws OmsBaseException {
        ModelAndView mv = new ModelAndView("advancequote/advanceProductPhenPriceTable");
        FixedErpProductForOmsQuery query  = FixedErpProductForOmsQuery.builder()
                .bizType(bizType)
                .brandId(brandId)
                .channelId(channelId)
                .cityId(cityId)
                .ecProductId(productId)
                .phenomenonId(phenId)
                .build();
        logger.info("故障现象获取价格表信息 入参：{}", JSON.toJSONString(query));
        ResponseDTO<List<FixedErpProductForOmsDRO>> responseDTO = fixedFlowRemoteService.listErpProductFilterPhenoForOmsByQuery(query);
        logger.info("故障现象获取价格表信息 出参：{}", JSON.toJSONString(responseDTO));

        PhenPriceVO phenPriceVO = this.getPhenPriceVO(phenName, responseDTO.getData(), categId, backProductId);
        mv.addObject("phenPriceList", Lists.newArrayList(phenPriceVO));
        return mv;
    }

    private PhenPriceVO getPhenPriceVO(String phenName, List<FixedErpProductForOmsDRO> productList, Integer categId, Integer backProductId) {
        PhenPriceVO priceVO = new PhenPriceVO();
        priceVO.setPhenName(phenName);
        priceVO.setRowspan(0);

        List<PhenPriceListVO> productItmeList = Lists.newArrayList();
        priceVO.setProductList(productItmeList);
        if (CollectionUtil.isNullOrEmpty(productList)) {
            return priceVO;
        }

        // 组装每一个产品下的故障 & 服务项
        productList.forEach(product -> {
            // 过滤后台产品
            if (NumberUtil.isNotNullOrZero(backProductId) && !Objects.equals(backProductId, product.getProductId())) {
                return;
            }
            // 过滤产品二级分类
            if (NumberUtil.isNotNullOrZero(categId) && !Objects.equals(categId, product.getCategId())) {
                return;
            }

            PhenPriceListVO priceItem = new PhenPriceListVO();
            priceItem.setProductId(product.getProductId());
            priceItem.setProductName(product.getProductName());

            List<PhenFaultPriceListVO> faultList = Lists.newArrayList();
            priceItem.setFaultList(faultList);
            if (CollectionUtil.isNullOrEmpty(product.getItemDROList())) {
                return;
            }

            // 有故障数据
            // 1. 将服务项数据处理
            Map<Integer, FixedItemSimpleDRO> itemMap = product.getItemDROList().stream().collect(Collectors.toMap(FixedItemSimpleDRO::getItemId, Function.identity(), (e1, e2) -> e1));

            // 临时缓存
            Map<Integer, PhenFaultPriceListVO> faultMap = Maps.newHashMap();

            // 收集所有故障、服务项对应信息
            product.getItemDROList().forEach(item -> {
                // 无故障 - 服务项对应关系 不展示
                if (CollectionUtil.isNullOrEmpty(item.getFaultDROList())) {
                    return;
                }
                PhenServiceItemPriceVO itemPriceVO = new PhenServiceItemPriceVO(item.getItemName(), item.getItemTypeName(), item.getPrice(), item.getItemUnit());

                item.getFaultDROList().forEach(fault -> {
                    PhenFaultPriceListVO faultPriceListVO = faultMap.get(fault.getFaultId());
                    if (Objects.isNull(faultPriceListVO)) {
                        faultPriceListVO = new PhenFaultPriceListVO();
                        faultPriceListVO.setFaultName(fault.getFaultName());
                        faultPriceListVO.setItemList(Lists.newArrayList());
                        faultMap.put(fault.getFaultId(), faultPriceListVO);
                    }
                    faultPriceListVO.getItemList().add(itemPriceVO);
                });
            });

            priceItem.setFaultList(Lists.newArrayList(faultMap.values()));

            Integer productRowspan = priceItem.getFaultList().stream().mapToInt(fault -> fault.getItemList().size()).sum();
            priceItem.setRowspan(productRowspan);

            productItmeList.add(priceItem);
        });

        priceVO.setRowspan(priceVO.getProductList().stream().mapToInt(PhenPriceListVO::getRowspan).sum());

        return priceVO;
    }


}
